﻿using System;
using System.Diagnostics;
using System.Globalization;
using System.Threading;

namespace HslCommunication.Core
{
	/// <summary>
	/// 一个高性能的读写锁，支持写锁定，读灵活，读时写锁定，写时读锁定
	/// </summary>
	// Token: 0x0200011D RID: 285
	public sealed class HslReadWriteLock : IDisposable
	{
		// Token: 0x0600188C RID: 6284 RVA: 0x0007D03C File Offset: 0x0007B23C
		private static HslReadWriteLock.OneManyLockStates State(int ls)
		{
			return (HslReadWriteLock.OneManyLockStates)(ls & 7);
		}

		// Token: 0x0600188D RID: 6285 RVA: 0x0007D051 File Offset: 0x0007B251
		private static void SetState(ref int ls, HslReadWriteLock.OneManyLockStates newState)
		{
			ls = ((ls & -8) | (int)newState);
		}

		// Token: 0x0600188E RID: 6286 RVA: 0x0007D060 File Offset: 0x0007B260
		private static int NumReadersReading(int ls)
		{
			return (ls & 4088) >> 3;
		}

		// Token: 0x0600188F RID: 6287 RVA: 0x0007D07B File Offset: 0x0007B27B
		private static void AddReadersReading(ref int ls, int amount)
		{
			ls += 8 * amount;
		}

		// Token: 0x06001890 RID: 6288 RVA: 0x0007D088 File Offset: 0x0007B288
		private static int NumReadersWaiting(int ls)
		{
			return (ls & 2093056) >> 12;
		}

		// Token: 0x06001891 RID: 6289 RVA: 0x0007D0A4 File Offset: 0x0007B2A4
		private static void AddReadersWaiting(ref int ls, int amount)
		{
			ls += 4096 * amount;
		}

		// Token: 0x06001892 RID: 6290 RVA: 0x0007D0B4 File Offset: 0x0007B2B4
		private static int NumWritersWaiting(int ls)
		{
			return (ls & 1071644672) >> 21;
		}

		// Token: 0x06001893 RID: 6291 RVA: 0x0007D0D0 File Offset: 0x0007B2D0
		private static void AddWritersWaiting(ref int ls, int amount)
		{
			ls += 2097152 * amount;
		}

		// Token: 0x06001894 RID: 6292 RVA: 0x0007D0E0 File Offset: 0x0007B2E0
		private static bool AnyWaiters(int ls)
		{
			return (ls & 1073737728) != 0;
		}

		// Token: 0x06001895 RID: 6293 RVA: 0x0007D0FC File Offset: 0x0007B2FC
		private static string DebugState(int ls)
		{
			return string.Format(CultureInfo.InvariantCulture, "State={0}, RR={1}, RW={2}, WW={3}", new object[]
			{
				HslReadWriteLock.State(ls),
				HslReadWriteLock.NumReadersReading(ls),
				HslReadWriteLock.NumReadersWaiting(ls),
				HslReadWriteLock.NumWritersWaiting(ls)
			});
		}

		/// <summary>
		/// 返回本对象的描述字符串
		/// </summary>
		/// <returns>对象的描述字符串</returns>
		// Token: 0x06001896 RID: 6294 RVA: 0x0007D15C File Offset: 0x0007B35C
		public override string ToString()
		{
			return HslReadWriteLock.DebugState(this.m_LockState);
		}

		// Token: 0x06001898 RID: 6296 RVA: 0x0007D1B4 File Offset: 0x0007B3B4
		private void Dispose(bool disposing)
		{
			bool flag = !this.disposedValue;
			if (flag)
			{
				if (disposing)
				{
				}
				this.m_WritersLock.Close();
				this.m_WritersLock = null;
				this.m_ReadersLock.Close();
				this.m_ReadersLock = null;
				this.disposedValue = true;
			}
		}

		/// <summary>
		/// 释放资源
		/// </summary>
		// Token: 0x06001899 RID: 6297 RVA: 0x0007D205 File Offset: 0x0007B405
		public void Dispose()
		{
			this.Dispose(true);
		}

		/// <summary>
		/// 根据读写情况请求锁
		/// </summary>
		/// <param name="exclusive">True为写请求，False为读请求</param>
		// Token: 0x0600189A RID: 6298 RVA: 0x0007D210 File Offset: 0x0007B410
		public void Enter(bool exclusive)
		{
			if (exclusive)
			{
				while (HslReadWriteLock.WaitToWrite(ref this.m_LockState))
				{
					this.m_WritersLock.WaitOne();
				}
			}
			else
			{
				while (HslReadWriteLock.WaitToRead(ref this.m_LockState))
				{
					this.m_ReadersLock.WaitOne();
				}
			}
			this.m_exclusive = exclusive;
		}

		// Token: 0x0600189B RID: 6299 RVA: 0x0007D26C File Offset: 0x0007B46C
		private static bool WaitToWrite(ref int target)
		{
			int num = target;
			int num2;
			bool result;
			do
			{
				num2 = num;
				int num3 = num2;
				result = false;
				switch (HslReadWriteLock.State(num3))
				{
				case HslReadWriteLock.OneManyLockStates.Free:
				case HslReadWriteLock.OneManyLockStates.ReservedForWriter:
					HslReadWriteLock.SetState(ref num3, HslReadWriteLock.OneManyLockStates.OwnedByWriter);
					break;
				case HslReadWriteLock.OneManyLockStates.OwnedByWriter:
					HslReadWriteLock.AddWritersWaiting(ref num3, 1);
					result = true;
					break;
				case HslReadWriteLock.OneManyLockStates.OwnedByReaders:
				case HslReadWriteLock.OneManyLockStates.OwnedByReadersAndWriterPending:
					HslReadWriteLock.SetState(ref num3, HslReadWriteLock.OneManyLockStates.OwnedByReadersAndWriterPending);
					HslReadWriteLock.AddWritersWaiting(ref num3, 1);
					result = true;
					break;
				default:
					Debug.Assert(false, "Invalid Lock state");
					break;
				}
				num = Interlocked.CompareExchange(ref target, num3, num2);
			}
			while (num2 != num);
			return result;
		}

		/// <summary>
		/// 释放锁，将根据锁状态自动区分读写锁
		/// </summary>
		// Token: 0x0600189C RID: 6300 RVA: 0x0007D30C File Offset: 0x0007B50C
		public void Leave()
		{
			bool exclusive = this.m_exclusive;
			int num;
			if (exclusive)
			{
				Debug.Assert(HslReadWriteLock.State(this.m_LockState) == HslReadWriteLock.OneManyLockStates.OwnedByWriter && HslReadWriteLock.NumReadersReading(this.m_LockState) == 0);
				num = HslReadWriteLock.DoneWriting(ref this.m_LockState);
			}
			else
			{
				HslReadWriteLock.OneManyLockStates oneManyLockStates = HslReadWriteLock.State(this.m_LockState);
				Debug.Assert(HslReadWriteLock.State(this.m_LockState) == HslReadWriteLock.OneManyLockStates.OwnedByReaders || HslReadWriteLock.State(this.m_LockState) == HslReadWriteLock.OneManyLockStates.OwnedByReadersAndWriterPending);
				num = HslReadWriteLock.DoneReading(ref this.m_LockState);
			}
			bool flag = num == -1;
			if (flag)
			{
				this.m_WritersLock.Release();
			}
			else
			{
				bool flag2 = num > 0;
				if (flag2)
				{
					this.m_ReadersLock.Release(num);
				}
			}
		}

		// Token: 0x0600189D RID: 6301 RVA: 0x0007D3C8 File Offset: 0x0007B5C8
		private static int DoneWriting(ref int target)
		{
			int num = target;
			int num2;
			int num4;
			do
			{
				int num3;
				num2 = (num3 = num);
				bool flag = !HslReadWriteLock.AnyWaiters(num3);
				if (flag)
				{
					HslReadWriteLock.SetState(ref num3, HslReadWriteLock.OneManyLockStates.Free);
					num4 = 0;
				}
				else
				{
					bool flag2 = HslReadWriteLock.NumWritersWaiting(num3) > 0;
					if (flag2)
					{
						HslReadWriteLock.SetState(ref num3, HslReadWriteLock.OneManyLockStates.ReservedForWriter);
						HslReadWriteLock.AddWritersWaiting(ref num3, -1);
						num4 = -1;
					}
					else
					{
						num4 = HslReadWriteLock.NumReadersWaiting(num3);
						Debug.Assert(num4 > 0);
						HslReadWriteLock.SetState(ref num3, HslReadWriteLock.OneManyLockStates.OwnedByReaders);
						HslReadWriteLock.AddReadersWaiting(ref num3, -num4);
					}
				}
				num = Interlocked.CompareExchange(ref target, num3, num2);
			}
			while (num2 != num);
			return num4;
		}

		// Token: 0x0600189E RID: 6302 RVA: 0x0007D46C File Offset: 0x0007B66C
		private static bool WaitToRead(ref int target)
		{
			int num = target;
			int num2;
			bool result;
			do
			{
				int num3;
				num2 = (num3 = num);
				result = false;
				switch (HslReadWriteLock.State(num3))
				{
				case HslReadWriteLock.OneManyLockStates.Free:
					HslReadWriteLock.SetState(ref num3, HslReadWriteLock.OneManyLockStates.OwnedByReaders);
					HslReadWriteLock.AddReadersReading(ref num3, 1);
					break;
				case HslReadWriteLock.OneManyLockStates.OwnedByWriter:
				case HslReadWriteLock.OneManyLockStates.OwnedByReadersAndWriterPending:
				case HslReadWriteLock.OneManyLockStates.ReservedForWriter:
					HslReadWriteLock.AddReadersWaiting(ref num3, 1);
					result = true;
					break;
				case HslReadWriteLock.OneManyLockStates.OwnedByReaders:
					HslReadWriteLock.AddReadersReading(ref num3, 1);
					break;
				default:
					Debug.Assert(false, "Invalid Lock state");
					break;
				}
				num = Interlocked.CompareExchange(ref target, num3, num2);
			}
			while (num2 != num);
			return result;
		}

		// Token: 0x0600189F RID: 6303 RVA: 0x0007D508 File Offset: 0x0007B708
		private static int DoneReading(ref int target)
		{
			int num = target;
			int num2;
			int result;
			do
			{
				int num3;
				num2 = (num3 = num);
				HslReadWriteLock.AddReadersReading(ref num3, -1);
				bool flag = HslReadWriteLock.NumReadersReading(num3) > 0;
				if (flag)
				{
					result = 0;
				}
				else
				{
					bool flag2 = !HslReadWriteLock.AnyWaiters(num3);
					if (flag2)
					{
						HslReadWriteLock.SetState(ref num3, HslReadWriteLock.OneManyLockStates.Free);
						result = 0;
					}
					else
					{
						Debug.Assert(HslReadWriteLock.NumWritersWaiting(num3) > 0);
						HslReadWriteLock.SetState(ref num3, HslReadWriteLock.OneManyLockStates.ReservedForWriter);
						HslReadWriteLock.AddWritersWaiting(ref num3, -1);
						result = -1;
					}
				}
				num = Interlocked.CompareExchange(ref target, num3, num2);
			}
			while (num2 != num);
			return result;
		}

		// Token: 0x0400056A RID: 1386
		private const int c_lsStateStartBit = 0;

		// Token: 0x0400056B RID: 1387
		private const int c_lsReadersReadingStartBit = 3;

		// Token: 0x0400056C RID: 1388
		private const int c_lsReadersWaitingStartBit = 12;

		// Token: 0x0400056D RID: 1389
		private const int c_lsWritersWaitingStartBit = 21;

		// Token: 0x0400056E RID: 1390
		private const int c_lsStateMask = 7;

		// Token: 0x0400056F RID: 1391
		private const int c_lsReadersReadingMask = 4088;

		// Token: 0x04000570 RID: 1392
		private const int c_lsReadersWaitingMask = 2093056;

		// Token: 0x04000571 RID: 1393
		private const int c_lsWritersWaitingMask = 1071644672;

		// Token: 0x04000572 RID: 1394
		private const int c_lsAnyWaitingMask = 1073737728;

		// Token: 0x04000573 RID: 1395
		private const int c_ls1ReaderReading = 8;

		// Token: 0x04000574 RID: 1396
		private const int c_ls1ReaderWaiting = 4096;

		// Token: 0x04000575 RID: 1397
		private const int c_ls1WriterWaiting = 2097152;

		// Token: 0x04000576 RID: 1398
		private int m_LockState = 0;

		// Token: 0x04000577 RID: 1399
		private Semaphore m_ReadersLock = new Semaphore(0, int.MaxValue);

		// Token: 0x04000578 RID: 1400
		private Semaphore m_WritersLock = new Semaphore(0, int.MaxValue);

		// Token: 0x04000579 RID: 1401
		private bool disposedValue = false;

		// Token: 0x0400057A RID: 1402
		private bool m_exclusive;

		// Token: 0x02000745 RID: 1861
		private enum OneManyLockStates
		{
			// Token: 0x04002E0F RID: 11791
			Free,
			// Token: 0x04002E10 RID: 11792
			OwnedByWriter,
			// Token: 0x04002E11 RID: 11793
			OwnedByReaders,
			// Token: 0x04002E12 RID: 11794
			OwnedByReadersAndWriterPending,
			// Token: 0x04002E13 RID: 11795
			ReservedForWriter
		}
	}
}
